//
// Scheduler.h
// Usage: Process scheduler
// CreateDate: 2009-04-20
// Author: CaiRuicheng
//==============================================================================
// 2009-06-09 Add function SelectScheduleObject(), select next process to run(M)
//			
#ifndef _SCHEDULER_H_
#define _SCHEDULER_H_

#include <LinkedList.h>
#include <SCI.h>
#include "ScheduleObject.h"
#include "../intrman/Callout.h"

enum SCHEDULE_QUEUE_TYPE {
	dev = 0,		   
	usr,			//1,2,3
	daemon,
	idle,
	block,
	SCHEDULE_QUEUE_SIZE
};

class CScheduler : public Callable
{
private:
	LinkedList<ScheduleObject *> m_ScheduleQueue[SCHEDULE_QUEUE_SIZE];

public:
	CScheduler();
	~CScheduler();

public:
	void AddScheduleObject(ScheduleObject * so);
	void RemoveScheduleObject(ScheduleObject * so);
	void Block(pid_t pid);
	void WakeUp(pid_t pid);
	void Schedule();
	void SelectScheduleObject(ScheduleObject * so);

protected:
	void SwitchProcess(ScheduleObject * current, ScheduleObject * target);

private:
	class ScheduleCallout : public Callout
	{
	private:
		CScheduler * m_Target;
		static ScheduleCallout * instance;
		ScheduleCallout(CScheduler * target, u32 delay)
			: Callout(delay), m_Target(target) {}
	public:
		static ScheduleCallout * GetInstance(CScheduler * target, u32 delay)
		{
			if(instance==NULL)
				instance = new ScheduleCallout(target, delay);
			return instance;
		}
		static ScheduleCallout * GetInstance() { return instance; }
		virtual void operator() ()
		{
			timeout(this);
			m_Target->Schedule();
		}
	};
};

#endif

